package com.jg.visitor.service.impl;

import cn.hutool.core.io.FastByteArrayOutputStream;
import cn.hutool.extra.qrcode.QrCodeUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jg.visitor.GlobalConst;
import com.jg.visitor.common.bean.AppConfigs;
import com.jg.visitor.common.bean.PageDTO;
import com.jg.visitor.common.bean.ServiceCode;
import com.jg.visitor.common.bean.WechatInfoBean;
import com.jg.visitor.common.utils.*;
import com.jg.visitor.config.autoconfiguration.caffeinecache.service.CacheService;
import com.jg.visitor.config.exception.BaseException;
import com.jg.visitor.config.exception.JgException;
import com.jg.visitor.controller.dto.*;
import com.jg.visitor.controller.enums.EnterTypeEnums;
import com.jg.visitor.controller.enums.ProcessEnum;
import com.jg.visitor.controller.enums.VisitorApplyRecordStatusEnum;
import com.jg.visitor.controller.enums.VisitorRecordOperationEnum;
import com.jg.visitor.controller.vo.CarInformationVO;
import com.jg.visitor.controller.vo.SignInOutVo;
import com.jg.visitor.controller.vo.VisitorApplyRecordVO;
import com.jg.visitor.domain.*;
import com.jg.visitor.kafka.producer.MsgSendService;
import com.jg.visitor.mapper.VisitorApplyRecordMapper;
import com.jg.visitor.service.*;
import com.jg.visitor.mapper.VisitorInfoMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author Administrator
*  针对表【visitor_info(访客信息表)】的数据库操作Service实现
*  2022-04-25 23:43:30
*/
@Service
public class VisitorInfoServiceImpl extends ServiceImpl<VisitorInfoMapper, VisitorInfo> implements VisitorInfoService{

    @Resource
    private IdGeneratorUtils idGeneratorUtils;
    @Resource
    private UserService userService;
    @Resource
    private VisitorApplyRecordService visitorApplyRecordService;
    @Resource
    private HealthInfoService healthInfoService;
    @Resource
    private FileUploadRecordService fileUploadRecordService;
    @Resource
    private VisitorApplyRecordMapper visitorApplyRecordMapper;
    @Resource
    private CacheService cacheService;
    @Resource
    private SignRecordService signRecordService;
    @Resource
    private VisitorInfoMapper visitorInfoMapper;
    @Resource
    private AppConfigs appConfigs;
    @Resource
    private JsonService jsonService;
    @Resource
    private BlacklistService blacklistService;
    @Resource
    private MsgSendService msgSendService;

    @Override
    public VisitorInfoDTO selectLoginVisitorInfo() {
        //拿到当前用户的openid查询基本信息
        String loginOpenId = LoginHelper.getLoginVisitorOpenId();

        VisitorInfo loginVisitor = getOne(new QueryWrapper<VisitorInfo>().eq("open_id", loginOpenId));

        VisitorInfoDTO dto = new VisitorInfoDTO();

        if(loginVisitor != null){
            BeanUtils.copyProperties(loginVisitor,dto);
            //车辆信息，json特殊处理
            if(!StringUtils.isEmpty(loginVisitor.getVehicleInf())){
                CarInformationVO carInf = jsonService.jsonToObject(loginVisitor.getVehicleInf(), CarInformationVO.class);
                dto.setVehicleBrand(carInf.getBrand());
                dto.setPlateNumber(carInf.getPlateNumber());
            }
        }


        return dto;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public VisitorInfoDTO addOrEditVisitorInfo(VisitorInfoDTO dto) {
        //更新
        if(null != dto.getId()){
            VisitorInfo oldInfo = getById(dto.getId());

            if(null == oldInfo){
                throw new BaseException(-1,"修改的访客信息不存在！");
            }

            //身份证若更高，检验新的身份证是否被占用
//            if(!dto.getCardNumber().equals(oldInfo.getCardNumber())){
//                long count = count(new QueryWrapper<VisitorInfo>().eq("card_number", dto.getCardNumber()));
//                if(count > 0){
//                    throw new BaseException(-1,"身份证号已经被使用，请先申述解绑！");
//                }
//            }

            //信息更新
            BeanUtils.copyProperties(dto,oldInfo);
            String carInfJson = getCarInfJson(dto);
            oldInfo.setVehicleInf(carInfJson);

            //更新
            oldInfo.setGmtModified(DateTimeUtil.getTimeNow());
            oldInfo.updateById();
        }
        //新增
        else{
            long count = count(new QueryWrapper<VisitorInfo>().eq("card_number", dto.getCardNumber()));
            if(count > 0){
                throw new BaseException(-1,"身份证号已经被使用，请先申述解绑！");
            }

            String loginOpenId = LoginHelper.getLoginVisitorOpenId();
            if(StringUtils.isEmpty(loginOpenId)){
                throw new BaseException(-1,"访客信息异常，请重新进入小程序尝试！");
            }
            VisitorInfo newVisitorInfo = new VisitorInfo();
            BeanUtils.copyProperties(dto,newVisitorInfo);
            newVisitorInfo.setOpenId(loginOpenId);
            String carInfJson = getCarInfJson(dto);
            newVisitorInfo.setVehicleInf(carInfJson);
            //插入
            newVisitorInfo.setGmtModified(DateTimeUtil.getTimeNow());
            newVisitorInfo.insert();
        }

        return dto;
    }

    private String getCarInfJson(VisitorInfoDTO dto){
        CarInformationVO vo = new CarInformationVO();
        if(!EnterTypeEnums.WALK.getType().equals(dto.getEnterType())){
            vo.setBrand(dto.getVehicleBrand());
            vo.setPlateNumber(dto.getPlateNumber());
        }
        return jsonService.objectToJson(vo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addApproveRecord(VisitorApplyRecordVO dto) {
        String loginOpenId = LoginHelper.getLoginVisitorOpenId();
        if(StringUtils.isEmpty(loginOpenId)){
            throw new BaseException(-1,"访客信息异常！");
        }

        VisitorInfo visitor = getOne(new QueryWrapper<VisitorInfo>().eq("open_id", loginOpenId));

        //信息不能为空
        User user = checkInfoFlag(dto,visitor);

        //优先入库健康表
        VisitorApplyRecordVO.Health health = dto.getHealthInfo();
        HealthInfo healthInfo = new HealthInfo();
        BeanUtils.copyProperties(health,healthInfo);
        healthInfo.insert();

        //再入库申请记录表
        VisitorApplyRecordVO.VisitorApplyRecordInfo recordInfo = dto.getApplyRecordInfo();
        VisitorApplyRecord record = new VisitorApplyRecord();
        BeanUtils.copyProperties(recordInfo,record);

        //设置健康信息，设置申请单状态为待被访者审批
        record.setHealthInfoId(healthInfo.getId());
        record.setStatus(VisitorApplyRecordStatusEnum.WAIT_RESPONDENTS_APPROVE.getStatusCode());

        //入库
        record.setApplyOrderNum(getApplyOrderNum());
        record.setGmtCreate(DateTimeUtil.getTimeNow());
        record.setGmtModified(DateTimeUtil.getTimeNow());

        //访客信息
        String visitorJson = jsonService.objectToJson(visitor);
        record.setVisitorInfoJson(visitorJson);
        record.insert();

        //保存操作记录
        OperationRecord operationRecord = new OperationRecord();
        operationRecord.setApplyRecordId(record.getId());
        operationRecord.setOperationType(VisitorRecordOperationEnum.ADD_NEW_RECORD.getOperationCode());
        operationRecord.setOperatorName(visitor.getUsername());
        operationRecord.setApplyFlag(GlobalConst.APPLY);
        operationRecord.setOperatorTime(DateTimeUtil.getTimeNow());
        operationRecord.setOldStatus(VisitorApplyRecordStatusEnum.NOT_CREATE.getStatusCode());
        operationRecord.setNewStatus(VisitorApplyRecordStatusEnum.WAIT_RESPONDENTS_APPROVE.getStatusCode());
        operationRecord.setAdminFlag(GlobalConst.ADMIN_FLAG_FALSE);
        operationRecord.setOperatorId(visitor.getId());

        operationRecord.insert();

        //给被访者推送消息审批
        sendKafkaMsg(record.getApplyOrderNum(), visitor.getUsername(),user.getOpenId(), ProcessEnum.WAIT_APPROVE);
    }

    public void sendKafkaMsg(String applyOrderNum,
                             String customerName,
                             String openId,
                             ProcessEnum processEnum){
        WechatInfoBean wechatInfoBean = new WechatInfoBean();
        wechatInfoBean.setApplyOrderNum(applyOrderNum);
        wechatInfoBean.setUsername(customerName);
        wechatInfoBean.setProcessEnum(processEnum);
        wechatInfoBean.setOpenId(openId);

        msgSendService.sendWechatMsg(wechatInfoBean);
    }

    public String getApplyOrderNum(){
        return DateTimeUtil.getTimeNowOnlyYear() + idGeneratorUtils.snowflakeId();
    }

    @Override
    public PageDTO<ApproverApproveRecordDTO> selectSelfRecord(Integer page, Integer pageSize, Integer status) {
        //先查询自己的id
        String openId = LoginHelper.getLoginVisitorOpenId();
        VisitorInfo one = getOne(new QueryWrapper<VisitorInfo>().eq("open_id", openId).select("id"));
        if(one == null){
            throw new BaseException(-1,"当前访客信息异常,请重新进入小程序后尝试！");
        }

        //查询条件
        QueryWrapper<VisitorApplyRecord> wrapper = new QueryWrapper<VisitorApplyRecord>()
                .eq("visitor_info_id", one.getId()).orderByDesc("gmt_create");
        if(status != null){
            List<Integer> statusCondition = GlobalConst.GET_APPLY_RECORD_STATUS_CONVERT_MAP().get(status);
            if(!CollectionUtils.isEmpty(statusCondition)){
                wrapper.in("status",statusCondition);
            }
        }

        PageDTO<ApproverApproveRecordDTO> ret = new PageDTO<>();

        //都不为空进行分页
        List<VisitorApplyRecord> dataList = pageVisitorApplyRecord(page,pageSize,wrapper,ret);
        List<Long> applyRecordIdList = dataList.stream().map(VisitorApplyRecord::getId).collect(Collectors.toList());

        ret.setPage(page);
        ret.setPageSize(pageSize);

        //没有数据直接返回
        if(CollectionUtils.isEmpty(dataList)){
            ret.setData(new ArrayList<>());
            ret.setTotal(0L);
            return ret;
        }


        //查询单子的健康记录表
        List<Long> healthIdList = dataList.stream().map(VisitorApplyRecord::getHealthInfoId).distinct().collect(Collectors.toList());
        List<HealthInfo> healthList = healthInfoService.list(new QueryWrapper<HealthInfo>().in("id", healthIdList));

        //找到被拒绝的单子，查出操作记录表拒绝原因
        List<OperationRecord> refuseRecordList = visitorApplyRecordService.getRefuseRecordList(dataList);

        //查询图片
        List<Long> imgIdList = healthList
                .stream()
                .map(healthInfo -> {
                    List<Long> idList = new ArrayList<>();
                    idList.add(healthInfo.getHealthPictureId());
                    idList.add(healthInfo.getTripPictureId());
                    idList.add(healthInfo.getNucleicPictureId());
                    return idList;
                })
                .flatMap(List::stream)
                .distinct()
                .collect(Collectors.toList());
        List<FileUploadRecord> allImg = CollectionUtils.isEmpty(imgIdList) ?
                new ArrayList<>() : fileUploadRecordService.listByIds(imgIdList);

        //查询进出记录
        List<SignRecord> allSignRecord = CollectionUtils.isEmpty(applyRecordIdList) ?
                new ArrayList<>() :
                signRecordService.list(new QueryWrapper<SignRecord>().in("visitor_apply_id",applyRecordIdList));

        //组装数据
        List<ApproverApproveRecordDTO> retDTOList = dataList
                .stream()
                .map(applyRecord -> {
                    ApproverApproveRecordDTO dto = new ApproverApproveRecordDTO();

                    VisitorInfo visitorInfo = one;
                    if (StringUtils.isEmpty(visitorInfo.getCardNumber())) {
                        visitorInfo = jsonService.jsonToObject(applyRecord.getVisitorInfoJson(), VisitorInfo.class);
                    }
                    VisitorInfoDTO visitorInfoDTO = new VisitorInfoDTO();
                    BeanUtils.copyProperties(visitorInfo, visitorInfoDTO);
                    if (!com.jg.visitor.common.utils.StringUtils.isEmpty(visitorInfo.getVehicleInf())) {
                        CarInformationVO informationVO = jsonService
                                .jsonToObject(visitorInfo.getVehicleInf(), CarInformationVO.class);
                        visitorInfoDTO.setPlateNumber(informationVO.getPlateNumber());
                        visitorInfoDTO.setVehicleBrand(informationVO.getBrand());
                    }
                    VisitorApplyRecordDTO recordDTO = visitorApplyRecordService
                            .getVisitorApplyRecordDTOByVisitorApplyRecord(applyRecord, healthList, allImg, refuseRecordList, allSignRecord);

                    dto.setVisitorInfoDTO(visitorInfoDTO);
                    dto.setVisitorApplyRecordDTO(recordDTO);
                    return dto;
                })
                .collect(Collectors.toList());

        ret.setData(retDTOList);

        return ret;
    }

    private List<VisitorApplyRecord> pageVisitorApplyRecord(Integer page,
                            Integer pageSize,
                            QueryWrapper<VisitorApplyRecord> wrapper,
                            PageDTO<?> ret){
        List<VisitorApplyRecord> dataList;
        //都不为空进行分页
        if(!CheckParamUtils.isAnyParamNull(page,pageSize)){
            Page<VisitorApplyRecord> pageData =new Page<>(page,pageSize);
            visitorApplyRecordService.page(pageData,wrapper);
            dataList = pageData.getRecords();
            ret.setTotal(pageData.getTotal());
        }
        else{
            dataList = visitorApplyRecordService.list(wrapper);
            ret.setTotal(dataList.size());
        }

        return dataList;
    }

    public User checkInfoFlag(VisitorApplyRecordVO dto,VisitorInfo visitorInfo){
        //其中一个对象为null即说明有问题
        if(CheckParamUtils.isAnyParamNull(dto.getApplyRecordInfo(),dto.getHealthInfo())){
            throw new JgException(ServiceCode.BAD_REQUEST);
        }

        //黑名单不允许申请
        int count = blacklistService.count(new QueryWrapper<Blacklist>().eq("visitor_id", visitorInfo.getId()));
        if(count > 0){
            throw new BaseException(-1,"网络繁忙！");
        }

        //被访者检验，没有此被访者提示
        User user = userService.getOne(new QueryWrapper<User>()
                .eq("username", dto.getApplyRecordInfo().getContactsPhone())
                .and(a -> a
                        .eq("type",GlobalConst.USER_TYPE_INTERVIEWEE)
                        .or()
                        .eq("type",GlobalConst.USER_TYPE_SAFETY_OFFICER)));

        if(user == null){
            throw new BaseException(-1,"没有找到被访者！");
        }

        String loginOpenId = LoginHelper.getLoginVisitorOpenId();

        if(loginOpenId == null){
            throw new BaseException(-1,"访客信息错误！");
        }

        if(GlobalConst.ENVIRONMENT_PRO.equals(appConfigs.getEnvironment()) && loginOpenId.equals(user.getOpenId())){
            throw new BaseException(-1,"不能向自己发起申请！");
        }

        if(!visitorCanAddRecord()){
            throw new BaseException(-1,"存在未完成记录！");
        }

        return user;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean idCardUnbound() {
        String loginOpenId = LoginHelper.getLoginVisitorOpenId();
        if(StringUtils.isEmpty(loginOpenId)){
            throw new BaseException(-1,"访客信息异常无法解绑！");
        }

        //现在只做清空访客信息功能，做到数据回显时没有身份信息，实际访客表与openId不能断连关系，否则查询不到历史申请数据
        //清空信息后，查询同行二维码时，校验当前访客身份证信息，不存在则不返回二维码
        VisitorInfo visitor = getOne(new QueryWrapper<VisitorInfo>().eq("open_id", loginOpenId));

        //查询是否还有在进行中的订单，如果有则不允许取消，因为管理员处理这些订单时需要查询用户信息
        if(!visitorCanAddRecord()){
            throw new BaseException(-1,"存在未完成的申请单，不能取消绑定！");
        }

        clearInfoExcludeCardNumber(visitor);
        visitor.setGmtModified(DateTimeUtil.getTimeNow());

        //mapper中此方法更新会更新null值
        return visitorInfoMapper.updateIncludeNull(visitor);
    }

    private void clearInfoExcludeCardNumber(VisitorInfo visitor){
        try{
            Class<VisitorInfo> infoClass = VisitorInfo.class;

            Field[] allField = infoClass.getDeclaredFields();

            for (Field field : allField) {
                field.setAccessible(true);
                //id与openId不清空
                if(!"id".equals(field.getName()) && !"openId".equals(field.getName())){
                    field.set(visitor,null);
                }
            }
        }
        catch (Exception e){
            log.error("clearInfoExcludeCardNumber error...",e);
            throw new BaseException(-1,"清空访客信息失败！");
        }
    }

    @Override
    public String getQRCode() {
        String loginOpenId = LoginHelper.getLoginVisitorOpenId();

        if(StringUtils.isEmpty(loginOpenId)){
            throw new BaseException(-1,"访客信息异常,请重新进入小程序！");
        }

        //查询通过了的申请单
        VisitorApplyRecord passedOrder = visitorApplyRecordMapper.getVisitorPassOrderByOpenId(loginOpenId,DateTimeUtil.getTimeNow());

        if(passedOrder == null){
            throw new BaseException(-1,"没有找到已审批通过的记录,不能获取通行码！");
        }

        //如果还没有到访问前1小时，则不返回通行码
        if(DateTimeUtil.getTimeAfterOneHour().compareTo(passedOrder.getBeginTime()) < 0){
            throw new BaseException(-1,"访问开始时间前1小时才能获取通行码！请稍后再试！");
        }


        //将已通过的订单信息与key存缓存,1分钟失效,也就是获取二维码后120秒内要给前台人员扫描处理，不然就失效了
        String qRCodeMapKey = idGeneratorUtils.snowflakeId() + "";

        cacheService.put(GlobalConst.VISITOR_PASS_CODE,qRCodeMapKey,passedOrder);

        //生成二维码并指定宽高
        BufferedImage generate = QrCodeUtil.generate(qRCodeMapKey, 800, 800);

        //转换流信息写出
        FastByteArrayOutputStream os = new FastByteArrayOutputStream();
        try {
            ImageIO.write(generate, "jpg", os);
        } catch (IOException e) {
            log.error("getQRCode error",e);
            throw new BaseException(-1,"获取二维码失败！");
        }

        //如果二维码要在前端显示需要转成Base64
        return GlobalConst.BASE64_HEADER_IMG + Base64.getEncoder().encodeToString(os.toByteArray());
    }

    @Override
    public PageDTO<OutInHistoryDTO> selectOutInHistory(Integer page,Integer pageSize) {

        UserDTO visitor = LoginHelper.getLoginVisitor();

        if(visitor == null){
            throw new BaseException(-1,"访客信息异常,请重新进入小程序！");
        }

        //分页返回对象
        PageDTO<OutInHistoryDTO> ret = new PageDTO<>();
        ret.setPage(page);
        ret.setPageSize(pageSize);

        //查询所有自己的签到签退记录,为空就直接返回
        QueryWrapper<SignRecord> queryWrapper = new QueryWrapper<SignRecord>().eq("visitor_id", visitor.getId());
        List<SignRecord> allSelfOperationRecords = signRecordService.list(queryWrapper);

        if(CollectionUtils.isEmpty(allSelfOperationRecords)){
            ret.setData(new ArrayList<>());
            return ret;
        }

        //分页查询拿到申请记录表数据
        List<Long> applyRecordIdList = allSelfOperationRecords
                .stream()
                .map(SignRecord::getVisitorApplyId)
                .distinct()
                .collect(Collectors.toList());
        QueryWrapper<VisitorApplyRecord> applyRecordQueryWrapper = new QueryWrapper<VisitorApplyRecord>().in("id",applyRecordIdList);
        List<VisitorApplyRecord> applyRecordList = pageVisitorApplyRecord(page,pageSize,applyRecordQueryWrapper,ret);

        List<OutInHistoryDTO> applyRecordSingInOutDTO = applyRecordList
                .stream()
                .map(record -> {
                    //找到所有的此单的签到签退记录
                    List<SignRecord> applyRecordOperationList = allSelfOperationRecords
                            .stream()
                            .filter(operationRecord -> operationRecord.getVisitorApplyId().equals(record.getId()))
                            .collect(Collectors.toList());
                    //找到第一次签到
                    String firstSignInTime = applyRecordOperationList
                            .stream()
                            .filter(operationRecord -> SignInOutVo.OperationEnum.SIGN_IN.getType()
                                    .equals(operationRecord.getSignType()))
                            .min(Comparator.comparing(SignRecord::getSignTime))
                            .map(SignRecord::getSignTime)
                            .orElse(null);
                    //找到最后一次签出
                    String lastSignOutTime = applyRecordOperationList
                            .stream()
                            .filter(operationRecord -> SignInOutVo.OperationEnum.SIGN_IN.getType()
                                    .equals(operationRecord.getSignType()))
                            .max(Comparator.comparing(SignRecord::getSignTime))
                            .map(SignRecord::getSignTime)
                            .orElse(null);
                    //每一单的基本返回信息
                    OutInHistoryDTO dto = new OutInHistoryDTO();
                    dto.setContacts(record.getContacts());
                    dto.setId(record.getId());
                    dto.setFirstEntryTime(firstSignInTime);
                    dto.setLastLeaveTime(lastSignOutTime);
                    dto.setApplyOrderNum(record.getApplyOrderNum());
                    //设置详细信息
                    List<OutInHistoryDTO.SignInOutDTO> detailDTO = applyRecordOperationList
                            .stream()
                            .map(operationRecord -> {
                                OutInHistoryDTO.SignInOutDTO signInOutDTO = new OutInHistoryDTO.SignInOutDTO();
                                signInOutDTO.setSignTime(operationRecord.getSignTime());
                                signInOutDTO.setSignType(operationRecord.getSignType());
                                signInOutDTO.setDoor(operationRecord.getDoor());
                                return signInOutDTO;
                            })
                            .sorted(Comparator.comparing(OutInHistoryDTO.SignInOutDTO::getSignTime))
                            .collect(Collectors.toList());
                    dto.setDetail(detailDTO);
                    return dto;
                })
                .collect(Collectors.toList());
        //返回数据
        ret.setData(applyRecordSingInOutDTO);

        //默认返回空对象
        return ret;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelApproveRecord(Long recordId) {
        UserDTO loginUser = LoginHelper.getLoginVisitor();
        if(null == loginUser){
            throw new BaseException(-1,"访客信息异常！");
        }

        if(null == recordId){
            throw new BaseException(-1,"请选择取消的申请单！");
        }

        VisitorApplyRecord record = visitorApplyRecordService
                .getOne(new QueryWrapper<VisitorApplyRecord>().eq("id", recordId).select("status","id"));

        if(record == null){
            throw new BaseException(-1,"没有找到需要取消的申请单！");
        }

        if(VisitorApplyRecordStatusEnum.CANCEL.getStatusCode().equals(record.getStatus())){
            throw new BaseException(-1,"已取消不能再次取消！");
        }

        if(VisitorApplyRecordStatusEnum.SIGN_IN.getStatusCode().equals(record.getStatus()) ||
                VisitorApplyRecordStatusEnum.SIGN_OUT.getStatusCode().equals(record.getStatus())){
            throw new BaseException(-1,"签到或签退后不能取消申请单！");
        }
        //操作记录
        OperationRecord operationRecord = new OperationRecord();
        operationRecord.setOldStatus(record.getStatus());

        //更新申请记录状态为取消
        record.setStatus(VisitorApplyRecordStatusEnum.CANCEL.getStatusCode());
        record.setGmtModified(DateTimeUtil.getTimeNow());
        record.updateById();

        //操作记录其他数据
        operationRecord.setApplyRecordId(recordId);
        operationRecord.setOperationType(VisitorRecordOperationEnum.CANCEL.getOperationCode());
        operationRecord.setOperatorTime(DateTimeUtil.getTimeNow());
        operationRecord.setAdminFlag(GlobalConst.ADMIN_FLAG_FALSE);
        operationRecord.setNewStatus(VisitorApplyRecordStatusEnum.CANCEL.getStatusCode());
        operationRecord.setApplyFlag(GlobalConst.APPLY);
        operationRecord.setOperatorId(LoginHelper.getLoginVisitor().getId());
        operationRecord.setOperatorName(LoginHelper.getLoginVisitor().getNickname());

        operationRecord.insert();
    }

    @Override
    public boolean visitorCanAddRecord() {
        //统计还有没有此访客没有完成的记录
        UserDTO loginVisitor = LoginHelper.getLoginVisitor();

        if(null == loginVisitor){
            throw new BaseException(-1,"访客信息异常！");
        }

        QueryWrapper<VisitorApplyRecord> queryWrapper = new QueryWrapper<VisitorApplyRecord>()
                //访客的
                .eq("visitor_info_id", loginVisitor.getId())
                //还在进行中的（状态为待XX或者是审批通过已签到已签退且当前时间小于结束时间的都认为进行中）
                .and(a -> a.in("status",VisitorApplyRecordStatusEnum.WAIT_RESPONDENTS_APPROVE.getStatusCode(), VisitorApplyRecordStatusEnum.WAIT_SAFER_APPROVE.getStatusCode())
                        .or()
                        .in("status",VisitorApplyRecordStatusEnum.PASS.getStatusCode(),
                                VisitorApplyRecordStatusEnum.SIGN_IN.getStatusCode(),VisitorApplyRecordStatusEnum.SIGN_OUT.getStatusCode())
                        .apply("convert(datetime,'" + DateTimeUtil.getTimeNow() + "') <= convert(datetime,end_time)"));
                
        long status = visitorApplyRecordService.count(queryWrapper);

        return status < 1;
    }

}




